அளவிடக்கூடிய, பராமரிக்கக்கூடிய மற்றும் சோதிக்கக்கூடிய பயன்பாடுகளை உருவாக்க FastAPI-யில் மேம்பட்ட சார்பு உட்செலுத்துதல் முறைகளை ஆராயுங்கள். ஒரு வலுவான DI கண்டெய்னரை எவ்வாறு கட்டமைப்பது என்பதை அறியுங்கள்.
FastAPI சார்பு உட்செலுத்துதல்: மேம்பட்ட DI கண்டெய்னர் கட்டமைப்பு
FastAPI, அதன் உள்ளுணர்வு வடிவமைப்பு மற்றும் சக்திவாய்ந்த அம்சங்களுடன், பைத்தானில் நவீன வலை API-களை உருவாக்குவதற்குப் பிடித்தமானதாக மாறியுள்ளது. அதன் முக்கிய பலங்களில் ஒன்று, சார்பு உட்செலுத்துதலுடன் (DI) தடையற்ற ஒருங்கிணைப்பில் உள்ளது. இது டெவலப்பர்களை தளர்வாக பிணைக்கப்பட்ட, சோதிக்கக்கூடிய மற்றும் பராமரிக்கக்கூடிய பயன்பாடுகளை உருவாக்க உதவுகிறது. FastAPI-யின் உள்ளமைக்கப்பட்ட DI அமைப்பு எளிய பயன்பாடுகளுக்குச் சிறப்பாக இருந்தாலும், மிகவும் சிக்கலான திட்டங்கள் ஒரு கட்டமைக்கப்பட்ட மற்றும் மேம்பட்ட DI கண்டெய்னர் கட்டமைப்பிலிருந்து பயனடைகின்றன. இந்த கட்டுரை அத்தகைய ஒரு கட்டமைப்பை உருவாக்குவதற்கான பல்வேறு உத்திகளை ஆராய்கிறது, வலுவான மற்றும் அளவிடக்கூடிய பயன்பாடுகளை வடிவமைப்பதற்கான நடைமுறை எடுத்துக்காட்டுகள் மற்றும் நுண்ணறிவுகளை வழங்குகிறது.
சார்பு உட்செலுத்துதல் (DI) மற்றும் கட்டுப்பாட்டின் தலைகீழ் (IoC) ஆகியவற்றைப் புரிந்துகொள்ளுதல்
மேம்பட்ட DI கண்டெய்னர் கட்டமைப்புகளுக்குள் செல்வதற்கு முன், அடிப்படைக் கருத்துக்களைத் தெளிவுபடுத்துவோம்:
- சார்பு உட்செலுத்துதல் (DI): ஒரு வடிவமைப்பு முறை, இதில் சார்புகள் ஒரு கூறுக்கு உள்ளிருந்து உருவாக்கப்படுவதற்குப் பதிலாக வெளிப்புற மூலங்களிலிருந்து வழங்கப்படுகின்றன. இது தளர்வான பிணைப்பை ஊக்குவிக்கிறது, இது கூறுகளைச் சோதிப்பதற்கும் மீண்டும் பயன்படுத்துவதற்கும் எளிதாக்குகிறது.
- கட்டுப்பாட்டின் தலைகீழ் (IoC): ஒரு பரந்த கொள்கை, இதில் பொருள் உருவாக்கம் மற்றும் நிர்வாகத்தின் கட்டுப்பாடு தலைகீழாக மாற்றப்படுகிறது - ஒரு கட்டமைப்பு அல்லது கண்டெய்னருக்கு ஒப்படைக்கப்படுகிறது. DI என்பது IoC-யின் ஒரு குறிப்பிட்ட வகை.
FastAPI அதன் சார்பு அமைப்பு மூலம் இயல்பாகவே DI-ஐ ஆதரிக்கிறது. நீங்கள் சார்புகளை அழைக்கக்கூடிய பொருட்களாக (செயல்பாடுகள், வகுப்புகள் போன்றவை) வரையறுக்கிறீர்கள், மேலும் FastAPI தானாகவே அவற்றை உங்கள் எண்ட்பாயிண்ட் செயல்பாடுகள் அல்லது பிற சார்புகளில் தீர்த்து உட்செலுத்துகிறது.
உதாரணம் (அடிப்படை FastAPI DI):
from fastapi import FastAPI, Depends
app = FastAPI()
# Dependency
def get_db():
db = {"items": []} # Simulate a database connection
try:
yield db
finally:
# Close the database connection (if needed)
pass
# Endpoint with dependency injection
@app.get("/items/")
async def read_items(db: dict = Depends(get_db)):
return db["items"]
இந்த எடுத்துக்காட்டில், get_db என்பது ஒரு தரவுத்தள இணைப்பை வழங்கும் ஒரு சார்பு ஆகும். FastAPI தானாகவே get_db-ஐ அழைத்து, அதன் முடிவை (db அகராதி) read_items எண்ட்பாயிண்ட் செயல்பாட்டில் உட்செலுத்துகிறது.
ஏன் ஒரு மேம்பட்ட DI கண்டெய்னர்?
FastAPI-யின் உள்ளமைக்கப்பட்ட DI எளிய திட்டங்களுக்கு நன்றாக வேலை செய்கிறது, ஆனால் பயன்பாடுகள் சிக்கலானதாக வளரும்போது, ஒரு மேம்பட்ட DI கண்டெய்னர் பல நன்மைகளை வழங்குகிறது:
- மையப்படுத்தப்பட்ட சார்பு மேலாண்மை: ஒரு பிரத்யேக கண்டெய்னர் அனைத்து சார்புகளுக்கும் ஒரே ஒரு உண்மையான மூலத்தை வழங்குகிறது, இது பயன்பாட்டின் சார்புகளை நிர்வகிப்பதையும் புரிந்துகொள்வதையும் எளிதாக்குகிறது.
- கட்டமைப்பு மற்றும் வாழ்க்கைச் சுழற்சி மேலாண்மை: கண்டெய்னர் சார்புகளின் கட்டமைப்பு மற்றும் வாழ்க்கைச் சுழற்சியைக் கையாள முடியும், அதாவது சிங்கிள்டன்களை உருவாக்குதல், இணைப்புகளை நிர்வகித்தல் மற்றும் வளங்களை அப்புறப்படுத்துதல்.
- சோதனைத்திறன்: ஒரு மேம்பட்ட கண்டெய்னர், போலியான பொருள்கள் அல்லது சோதனை இரட்டையர்களுடன் சார்புகளை எளிதாக மேலெழுத அனுமதிப்பதன் மூலம் சோதனையை எளிதாக்குகிறது.
- இணைப்பறுத்தல் (Decoupling): கூறுகளுக்கு இடையே அதிக இணைப்பறுத்தலை ஊக்குவிக்கிறது, சார்புகளைக் குறைத்து குறியீட்டின் பராமரிப்புத்திறனை மேம்படுத்துகிறது.
- விரிவாக்கத்திறன்: ஒரு விரிவாக்கக்கூடிய கண்டெய்னர் தேவைக்கேற்ப தனிப்பயன் அம்சங்களையும் ஒருங்கிணைப்புகளையும் சேர்க்க உங்களை அனுமதிக்கிறது.
ஒரு மேம்பட்ட DI கண்டெய்னரை உருவாக்குவதற்கான உத்திகள்
FastAPI-யில் ஒரு மேம்பட்ட DI கண்டெய்னரை உருவாக்க பல அணுகுமுறைகள் உள்ளன. இங்கே சில பொதுவான உத்திகள் உள்ளன:
1. பிரத்யேக DI நூலகத்தைப் பயன்படுத்துதல் (எ.கா., `injector`, `dependency_injector`)
பைத்தானுக்கு `injector` மற்றும் `dependency_injector` போன்ற பல சக்திவாய்ந்த DI நூலகங்கள் உள்ளன. இந்த நூலகங்கள் சார்புகளை நிர்வகிப்பதற்கான ஒரு விரிவான அம்சங்களை வழங்குகின்றன, அவற்றுள்:
- பிணைப்பு (Binding): சார்புகள் எவ்வாறு தீர்க்கப்பட்டு உட்செலுத்தப்படுகின்றன என்பதை வரையறுத்தல்.
- நோக்கங்கள் (Scopes): சார்புகளின் வாழ்க்கைச் சுழற்சியைக் கட்டுப்படுத்துதல் (எ.கா., சிங்கிள்டன், டிரான்சியன்ட்).
- கட்டமைப்பு (Configuration): சார்புகளுக்கான கட்டமைப்பு அமைப்புகளை நிர்வகித்தல்.
- AOP (Aspect-Oriented Programming): குறுக்குவெட்டு கவலைகளுக்காக முறை அழைப்புகளை இடைமறித்தல்.
`dependency_injector` உடன் உதாரணம்
`dependency_injector` என்பது DI கண்டெய்னர்களை உருவாக்குவதற்கான ஒரு பிரபலமான தேர்வாகும். அதன் பயன்பாட்டை ஒரு எடுத்துக்காட்டுடன் விளக்குவோம்:
from dependency_injector import containers, providers
from fastapi import FastAPI, Depends
# Define dependencies
class Database:
def __init__(self, connection_string: str):
self.connection_string = connection_string
# Initialize database connection
print(f"Connecting to database: {self.connection_string}")
def get_items(self):
# Simulate fetching items from the database
return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]
class UserRepository:
def __init__(self, database: Database):
self.database = database
def get_all_users(self):
# Simulating database request to get all users
return [{"id": "user1", "name": "Alice"},{"id": "user2", "name": "Bob"}]
class Settings:
def __init__(self, database_url):
self.database_url = database_url
# Define container
class Container(containers.DeclarativeContainer):
config = providers.Configuration()
settings = providers.Singleton(Settings, database_url = config.database_url)
database = providers.Singleton(Database, connection_string=config.database_url)
user_repository = providers.Factory(UserRepository, database=database)
# Create FastAPI app
app = FastAPI()
# Configure container (from an environment variable)
container = Container()
container.config.database_url.from_env("DATABASE_URL", default="sqlite:///:memory:")
container.wire([__name__]) # enables injection of dependencies into FastAPI endpoints
# Dependency for FastAPI
def get_user_repository(user_repository: UserRepository = Depends(container.user_repository.provided)) -> UserRepository:
return user_repository
# Endpoint using injected dependency
@app.get("/users/")
async def read_users(user_repository: UserRepository = Depends(get_user_repository)):
return user_repository.get_all_users()
@app.on_event("startup")
async def startup_event():
# Container initialization
container.init_resources()
விளக்கம்:
- எங்கள் சார்புகளை (
Database,UserRepository,Settings) சாதாரண பைத்தான் வகுப்புகளாக வரையறுக்கிறோம். - நாம்
containers.DeclarativeContainer-இலிருந்து பெறப்பட்ட ஒருContainerவகுப்பை உருவாக்குகிறோம். இந்த வகுப்பு சார்புகளையும் அவற்றின் வழங்குநர்களையும் (எ.கா., சிங்கிள்டன்களுக்குproviders.Singleton, ஒவ்வொரு முறையும் புதிய நிகழ்வுகளை உருவாக்கproviders.Factory) வரையறுக்கிறது. container.wire([__name__])வரி FastAPI எண்ட்பாயிண்ட்களில் சார்பு உட்செலுத்தலை செயல்படுத்துகிறது.get_user_repositoryசெயல்பாடு ஒரு FastAPI சார்பு ஆகும், இது கண்டெய்னரிலிருந்து UserRepository நிகழ்வைப் பெறcontainer.user_repository.provided-ஐப் பயன்படுத்துகிறது.- எண்ட்பாயிண்ட் செயல்பாடு
read_users,UserRepositoryசார்பை உட்செலுத்துகிறது. - `config` சார்பு கட்டமைப்புகளை வெளிப்புறப்படுத்த உங்களை அனுமதிக்கிறது. இது சூழல் மாறிகள், கட்டமைப்பு கோப்புகள் போன்றவற்றிலிருந்து வரலாம்.
- `startup_event` கண்டெய்னரில் நிர்வகிக்கப்படும் வளங்களைத் தொடங்கப் பயன்படுகிறது.
2. ஒரு தனிப்பயன் DI கண்டெய்னரை செயல்படுத்துதல்
DI செயல்முறையின் மீது அதிக கட்டுப்பாட்டிற்கு, நீங்கள் ஒரு தனிப்பயன் DI கண்டெய்னரை செயல்படுத்தலாம். இந்த அணுகுமுறைக்கு அதிக முயற்சி தேவைப்படுகிறது, ஆனால் உங்கள் குறிப்பிட்ட தேவைகளுக்கு ஏற்ப கண்டெய்னரைத் தனிப்பயனாக்க உங்களை அனுமதிக்கிறது.
அடிப்படை தனிப்பயன் DI கண்டெய்னர் உதாரணம்:
from typing import Callable, Dict, Type, Any
from fastapi import FastAPI, Depends
class Container:
def __init__(self):
self.dependencies: Dict[Type[Any], Callable[..., Any]] = {}
self.instances: Dict[Type[Any], Any] = {}
def register(self, dependency_type: Type[Any], provider: Callable[..., Any]):
self.dependencies[dependency_type] = provider
def resolve(self, dependency_type: Type[Any]) -> Any:
if dependency_type in self.instances:
return self.instances[dependency_type]
if dependency_type not in self.dependencies:
raise Exception(f"Dependency {dependency_type} not registered.")
provider = self.dependencies[dependency_type]
instance = provider()
return instance
def singleton(self, dependency_type: Type[Any], provider: Callable[..., Any]):
self.register(dependency_type, provider)
self.instances[dependency_type] = provider()
# Example Dependencies
class PaymentGateway:
def process_payment(self, amount: float) -> bool:
print(f"Processing payment of ${amount}")
return True # Simulate successful payment
class NotificationService:
def send_notification(self, message: str):
print(f"Sending notification: {message}")
# Example Usage
container = Container()
container.singleton(PaymentGateway, PaymentGateway)
container.singleton(NotificationService, NotificationService)
app = FastAPI()
# FastAPI Dependency
def get_payment_gateway(payment_gateway: PaymentGateway = Depends(lambda: container.resolve(PaymentGateway))):
return payment_gateway
def get_notification_service(notification_service: NotificationService = Depends(lambda: container.resolve(NotificationService))):
return notification_service
@app.post("/purchase/")
async def purchase_item(payment_gateway: PaymentGateway = Depends(get_payment_gateway), notification_service: NotificationService = Depends(get_notification_service)):
if payment_gateway.process_payment(100.0):
notification_service.send_notification("Purchase successful!")
return {"message": "Purchase successful"}
else:
return {"message": "Purchase failed"}
விளக்கம்:
Containerவகுப்பு சார்புகள் மற்றும் அவற்றின் வழங்குநர்களின் அகராதியை நிர்வகிக்கிறது.registerமுறை ஒரு சார்பை அதன் வழங்குநருடன் பதிவு செய்கிறது.resolveமுறை அதன் வழங்குநரை அழைத்து ஒரு சார்பைத் தீர்க்கிறது.singletonமுறை ஒரு சார்பைப் பதிவுசெய்து அதன் ஒரே ஒரு நிகழ்வை உருவாக்குகிறது.- FastAPI சார்புகள் கண்டெய்னரிலிருந்து சார்புகளைத் தீர்க்க ஒரு லாம்ப்டா செயல்பாட்டைப் பயன்படுத்தி உருவாக்கப்படுகின்றன.
3. ஒரு ஃபேக்டரி செயல்பாட்டுடன் FastAPI-யின் `Depends`-ஐப் பயன்படுத்துதல்
ஒரு முழுமையான DI கண்டெய்னருக்குப் பதிலாக, நீங்கள் சில நிலை சார்பு நிர்வாகத்தை அடைய ஃபேக்டரி செயல்பாடுகளுடன் FastAPI-யின் Depends-ஐப் பயன்படுத்தலாம். இந்த அணுகுமுறை ஒரு தனிப்பயன் கண்டெய்னரை செயல்படுத்துவதை விட எளிமையானது, ஆனால் எண்ட்பாயிண்ட் செயல்பாடுகளுக்குள் நேரடியாக சார்புகளை உருவாக்குவதை விட சில நன்மைகளை வழங்குகிறது.
from fastapi import FastAPI, Depends
from typing import Callable
# Define Dependencies
class EmailService:
def __init__(self, smtp_server: str):
self.smtp_server = smtp_server
def send_email(self, recipient: str, subject: str, body: str):
print(f"Sending email to {recipient} via {self.smtp_server}: {subject} - {body}")
# Factory function for EmailService
def create_email_service(smtp_server: str) -> EmailService:
return EmailService(smtp_server=smtp_server)
# FastAPI
app = FastAPI()
# FastAPI Dependency, leveraging factory function and Depends
def get_email_service(email_service: EmailService = Depends(lambda: create_email_service(smtp_server="smtp.example.com"))):
return email_service
@app.post("/send-email/")
async def send_email(recipient: str, subject: str, body: str, email_service: EmailService = Depends(get_email_service)):
email_service.send_email(recipient=recipient, subject=subject, body=body)
return {"message": "Email sent!"}
விளக்கம்:
- நாம் ஒரு ஃபேக்டரி செயல்பாட்டை (
create_email_service) வரையறுக்கிறோம், அதுEmailServiceசார்பின் நிகழ்வுகளை உருவாக்குகிறது. get_email_serviceசார்பு, ஃபேக்டரி செயல்பாட்டை அழைத்துEmailService-இன் ஒரு நிகழ்வை வழங்கDependsமற்றும் ஒரு லாம்ப்டாவைப் பயன்படுத்துகிறது.- எண்ட்பாயிண்ட் செயல்பாடு
send_email,EmailServiceசார்பை உட்செலுத்துகிறது.
மேம்பட்ட பரிசீலனைகள்
1. நோக்கங்கள் மற்றும் வாழ்க்கைச் சுழற்சிகள்
DI கண்டெய்னர்கள் பெரும்பாலும் சார்புகளின் வாழ்க்கைச் சுழற்சியை நிர்வகிப்பதற்கான அம்சங்களை வழங்குகின்றன. பொதுவான நோக்கங்கள் பின்வருமாறு:
- சிங்கிள்டன் (Singleton): சார்பின் ஒரே ஒரு நிகழ்வு உருவாக்கப்பட்டு, பயன்பாட்டின் வாழ்நாள் முழுவதும் மீண்டும் பயன்படுத்தப்படுகிறது. இது நிலை இல்லாத அல்லது உலகளாவிய நோக்கம் கொண்ட சார்புகளுக்கு ஏற்றது.
- டிரான்சியன்ட் (Transient): ஒவ்வொரு முறையும் கோரப்படும்போது சார்பின் ஒரு புதிய நிகழ்வு உருவாக்கப்படுகிறது. இது நிலை சார்ந்த அல்லது ஒன்றிலிருந்து ஒன்று பிரிக்கப்பட வேண்டிய சார்புகளுக்கு ஏற்றது.
- கோரிக்கை (Request): ஒவ்வொரு உள்வரும் கோரிக்கைக்கும் சார்பின் ஒரே ஒரு நிகழ்வு உருவாக்கப்படுகிறது. இது ஒரு கோரிக்கையின் சூழலில் நிலையை பராமரிக்க வேண்டிய சார்புகளுக்கு ஏற்றது.
dependency_injector நூலகம் நோக்கங்களுக்கான உள்ளமைக்கப்பட்ட ஆதரவை வழங்குகிறது. தனிப்பயன் கண்டெய்னர்களுக்கு, நீங்கள் நோக்கம் மேலாண்மை தர்க்கத்தை நீங்களே செயல்படுத்த வேண்டும்.
2. கட்டமைப்பு
சார்புகளுக்கு பெரும்பாலும் தரவுத்தள இணைப்பு சரங்கள், API விசைகள் மற்றும் அம்சக் கொடிகள் போன்ற கட்டமைப்பு அமைப்புகள் தேவைப்படுகின்றன. DI கண்டெய்னர்கள் இந்த அமைப்புகளை அணுகுவதற்கும் உட்செலுத்துவதற்கும் ஒரு மையப்படுத்தப்பட்ட வழியை வழங்குவதன் மூலம் அவற்றை நிர்வகிக்க உதவும்.
dependency_injector எடுத்துக்காட்டில், config வழங்குநர் சூழல் மாறிகளிலிருந்து கட்டமைப்பை அனுமதிக்கிறது. தனிப்பயன் கண்டெய்னர்களுக்கு, நீங்கள் கோப்புகள் அல்லது சூழல் மாறிகளிலிருந்து கட்டமைப்பை ஏற்றி அவற்றை கண்டெய்னரில் சேமிக்கலாம்.
3. சோதனை
DI-யின் முதன்மை நன்மைகளில் ஒன்று மேம்பட்ட சோதனைத்திறன் ஆகும். ஒரு DI கண்டெய்னருடன், சோதனையின் போது உண்மையான சார்புகளை போலியான பொருள்கள் அல்லது சோதனை இரட்டையர்களுடன் எளிதாக மாற்றலாம்.
உதாரணம் (`dependency_injector` உடன் சோதனை):
import pytest
from unittest.mock import MagicMock
from dependency_injector import containers, providers
from fastapi import FastAPI, Depends
from fastapi.testclient import TestClient
# Define dependencies (same as before)
class Database:
def __init__(self, connection_string: str):
self.connection_string = connection_string
def get_items(self):
return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]
class UserRepository:
def __init__(self, database: Database):
self.database = database
def get_all_users(self):
return [{"id": "user1", "name": "Alice"},{"id": "user2", "name": "Bob"}]
class Settings:
def __init__(self, database_url):
self.database_url = database_url
# Define container (same as before)
class Container(containers.DeclarativeContainer):
config = providers.Configuration()
settings = providers.Singleton(Settings, database_url = config.database_url)
database = providers.Singleton(Database, connection_string=config.database_url)
user_repository = providers.Factory(UserRepository, database=database)
# Create FastAPI app (same as before)
app = FastAPI()
# Configure container (from an environment variable)
container = Container()
container.config.database_url.from_env("DATABASE_URL", default="sqlite:///:memory:")
container.wire([__name__]) # enables injection of dependencies into FastAPI endpoints
# Dependency for FastAPI
def get_user_repository(user_repository: UserRepository = Depends(container.user_repository.provided)) -> UserRepository:
return user_repository
# Endpoint using injected dependency (same as before)
@app.get("/users/")
async def read_users(user_repository: UserRepository = Depends(get_user_repository)):
return user_repository.get_all_users()
@app.on_event("startup")
async def startup_event():
# Container initialization
container.init_resources()
# Test
@pytest.fixture
def test_client():
# Override the database dependency with a mock
database_mock = MagicMock(spec=Database)
database_mock.get_items.return_value = [{"id": 3, "name": "Test Item"}]
user_repository_mock = MagicMock(spec = UserRepository)
user_repository_mock.get_all_users.return_value = [{"id": "test_user", "name": "Test User"}]
# Override container with mock dependencies
container.user_repository.override(providers.Factory(lambda: user_repository_mock))
with TestClient(app) as client:
yield client
container.user_repository.reset()
def test_read_users(test_client: TestClient):
response = test_client.get("/users/")
assert response.status_code == 200
assert response.json() == [{"id": "test_user", "name": "Test User"}]
விளக்கம்:
- நாம்
MagicMock-ஐப் பயன்படுத்திDatabaseசார்புக்கு ஒரு போலியான பொருளை உருவாக்குகிறோம். - நாம்
container.database.override()-ஐப் பயன்படுத்தி கண்டெய்னரில் உள்ளdatabaseவழங்குநரை போலியான பொருளுடன் மேலெழுதுகிறோம். - சோதனை செயல்பாடு
test_read_itemsஇப்போது போலியான தரவுத்தள சார்பைப் பயன்படுத்துகிறது. - சோதனை முடிந்த பிறகு, அது கண்டெய்னரின் மேலெழுதப்பட்ட சார்பை மீட்டமைக்கிறது.
4. ஒத்திசைவற்ற சார்புகள்
FastAPI ஒத்திசைவற்ற நிரலாக்கத்தின் (async/await) மீது கட்டமைக்கப்பட்டுள்ளது. ஒத்திசைவற்ற சார்புகளுடன் (எ.கா., ஒத்திசைவற்ற தரவுத்தள இணைப்புகள்) வேலை செய்யும்போது, உங்கள் DI கண்டெய்னர் மற்றும் சார்பு வழங்குநர்கள் ஒத்திசைவற்ற செயல்பாடுகளை ஆதரிக்கின்றனவா என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்.
உதாரணம் (`dependency_injector` உடன் ஒத்திசைவற்ற சார்பு):
import asyncio
from dependency_injector import containers, providers
from fastapi import FastAPI, Depends
# Define asynchronous dependency
class AsyncDatabase:
def __init__(self, connection_string: str):
self.connection_string = connection_string
async def connect(self):
print(f"Connecting to database: {self.connection_string}")
await asyncio.sleep(0.1) # Simulate connection time
async def fetch_data(self):
await asyncio.sleep(0.1) # Simulate database query
return [{"id": 1, "name": "Async Item 1"}]
# Define container
class Container(containers.DeclarativeContainer):
config = providers.Configuration()
database = providers.Singleton(AsyncDatabase, connection_string=config.database_url)
# Create FastAPI app
app = FastAPI()
# Configure container
container = Container()
container.config.database_url.from_env("DATABASE_URL", default="sqlite:///:memory:")
container.wire([__name__])
# Dependency for FastAPI
async def get_async_database(database: AsyncDatabase = Depends(container.database.provided)) -> AsyncDatabase:
await database.connect()
return database
# Endpoint using injected dependency
@app.get("/async-items/")
async def read_async_items(database: AsyncDatabase = Depends(get_async_database)):
data = await database.fetch_data()
return data
@app.on_event("startup")
async def startup_event():
# Container initialization
container.init_resources()
விளக்கம்:
AsyncDatabaseவகுப்புasyncமற்றும்await-ஐப் பயன்படுத்தி ஒத்திசைவற்ற முறைகளை வரையறுக்கிறது.get_async_databaseசார்பும் ஒரு ஒத்திசைவற்ற செயல்பாடாக வரையறுக்கப்பட்டுள்ளது.- எண்ட்பாயிண்ட் செயல்பாடு
read_async_itemsasyncஎனக் குறிக்கப்பட்டுள்ளது மற்றும்database.fetch_data()-இன் முடிவிற்காக காத்திருக்கிறது.
சரியான அணுகுமுறையைத் தேர்ந்தெடுத்தல்
ஒரு மேம்பட்ட DI கண்டெய்னரை உருவாக்குவதற்கான சிறந்த அணுகுமுறை உங்கள் பயன்பாட்டின் சிக்கலான தன்மை மற்றும் உங்கள் குறிப்பிட்ட தேவைகளைப் பொறுத்தது:
- சிறிய மற்றும் நடுத்தர அளவிலான திட்டங்களுக்கு: FastAPI-யின் உள்ளமைக்கப்பட்ட DI அல்லது
Dependsஉடன் ஒரு ஃபேக்டரி செயல்பாடு அணுகுமுறை போதுமானதாக இருக்கலாம். - பெரிய, மிகவும் சிக்கலான திட்டங்களுக்கு:
dependency_injectorபோன்ற ஒரு பிரத்யேக DI நூலகம் சார்புகளை நிர்வகிப்பதற்கான ஒரு விரிவான அம்சங்களை வழங்குகிறது. - DI செயல்முறையின் மீது நுணுக்கமான கட்டுப்பாடு தேவைப்படும் திட்டங்களுக்கு: ஒரு தனிப்பயன் DI கண்டெய்னரை செயல்படுத்துவது சிறந்த தேர்வாக இருக்கலாம்.
முடிவுரை
சார்பு உட்செலுத்துதல் என்பது அளவிடக்கூடிய, பராமரிக்கக்கூடிய மற்றும் சோதிக்கக்கூடிய பயன்பாடுகளை உருவாக்குவதற்கான ஒரு சக்திவாய்ந்த நுட்பமாகும். FastAPI-யின் உள்ளமைக்கப்பட்ட DI அமைப்பு எளிய பயன்பாடுகளுக்குச் சிறப்பாக இருந்தாலும், ஒரு மேம்பட்ட DI கண்டெய்னர் கட்டமைப்பு மிகவும் சிக்கலான திட்டங்களுக்கு குறிப்பிடத்தக்க நன்மைகளை வழங்க முடியும். சரியான அணுகுமுறையைத் தேர்ந்தெடுத்து, DI நூலகங்களின் அம்சங்களைப் பயன்படுத்துவதன் மூலமோ அல்லது ஒரு தனிப்பயன் கண்டெய்னரை செயல்படுத்துவதன் மூலமோ, உங்கள் FastAPI பயன்பாடுகளின் ஒட்டுமொத்த தரம் மற்றும் பராமரிப்புத்திறனை மேம்படுத்தும் ஒரு வலுவான மற்றும் நெகிழ்வான சார்பு மேலாண்மை அமைப்பை நீங்கள் உருவாக்கலாம்.
உலகளாவிய பரிசீலனைகள்
உலகளாவிய பயன்பாடுகளுக்கான DI கண்டெய்னர்களை வடிவமைக்கும்போது, பின்வருவனவற்றைக் கருத்தில் கொள்வது அவசியம்:
- உள்ளூர்மயமாக்கல்: உள்ளூர்மயமாக்கல் தொடர்பான சார்புகள் (எ.கா., மொழி அமைப்புகள், தேதி வடிவங்கள்) வெவ்வேறு பிராந்தியங்களில் நிலைத்தன்மையை உறுதிசெய்ய DI கண்டெய்னரால் நிர்வகிக்கப்பட வேண்டும்.
- நேர மண்டலங்கள்: நேர மண்டல மாற்றங்களைக் கையாளும் சார்புகள், நேர மண்டலத் தகவலை ஹார்ட்கோட் செய்வதைத் தவிர்க்க உட்செலுத்தப்பட வேண்டும்.
- நாணயம்: நாணய மாற்றம் மற்றும் வடிவமைப்பிற்கான சார்புகள் வெவ்வேறு நாணயங்களை ஆதரிக்க கண்டெய்னரால் நிர்வகிக்கப்பட வேண்டும்.
- பிராந்திய அமைப்புகள்: எண் வடிவங்கள் மற்றும் முகவரி வடிவங்கள் போன்ற பிற பிராந்திய அமைப்புகளும் DI கண்டெய்னரால் நிர்வகிக்கப்பட வேண்டும்.
- பல-குத்தகை (Multi-tenancy): பல-குத்தகை பயன்பாடுகளுக்கு, DI கண்டெய்னர் வெவ்வேறு குத்தகைதாரர்களுக்கு வெவ்வேறு சார்புகளை வழங்க முடியும். இது நோக்கங்கள் அல்லது தனிப்பயன் சார்பு தீர்வு தர்க்கத்தைப் பயன்படுத்தி அடையலாம்.
- இணக்கம் மற்றும் பாதுகாப்பு: உங்கள் சார்பு மேலாண்மை உத்தி தொடர்புடைய தரவு தனியுரிமை விதிமுறைகளுடன் (எ.கா., GDPR, CCPA) மற்றும் பல்வேறு பிராந்தியங்களில் பாதுகாப்பு சிறந்த நடைமுறைகளுடன் இணங்குவதை உறுதிசெய்யவும். முக்கியமான நற்சான்றிதழ்கள் மற்றும் கட்டமைப்புகளை கண்டெய்னருக்குள் பாதுகாப்பாகக் கையாளவும்.
இந்த உலகளாவிய காரணிகளைக் கருத்தில் கொள்வதன் மூலம், உலகளாவிய சூழலில் செயல்படும் பயன்பாடுகளை உருவாக்குவதற்கு நன்கு பொருத்தமான DI கண்டெய்னர்களை நீங்கள் உருவாக்கலாம்.